package com.tianyadu.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @FileName: HystrixController
 * @Description:
 * @author: xueyj
 * @create: 2018-11-23 17:19
 */
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

    /**
      * @Description: 使用restTemplate调用商品服务信息
      * @param:
      * @return:
      * @author:
      * @date:   2018/11/26 22:25
      */
    @GetMapping("/getProductListByRestTemplate")
    public String getProductListByRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8081/product/listForOrder",
                Arrays.asList("157875196366160022"),
                String.class);
    }

    /**
      * @Description: 调用服务宕机，服务降级
      * @param:
      * @return:
      * @author:
      * @date:   2018/11/26 22:39
      */
    @HystrixCommand(fallbackMethod = "fallback")
    @GetMapping("/getProductListByServerShutdown")
    public String getProductListByServerShutdown() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8081/product/listForOrder",
                Arrays.asList("157875196366160022"),
                String.class);
        //  服务内部异常，也会触发服务降级
        //		throw new RuntimeException("发送异常了");
    }

    /**
      * @Description: 服务异常，触发降级
      * @param:
      * @return:
      * @author:
      * @date:   2018/11/26 22:46
      */
    @HystrixCommand(fallbackMethod = "fallback")
    @GetMapping("/getInfoByServerException")
    public String getInfoByServerException() {
        //  服务内部异常，会触发服务降级
        throw new RuntimeException("发送异常了");
    }

    /**
      * @Description: 调用服务降级默认提醒
      * @param:
      * @return:
      * @author:
      * @date:   2018/11/26 22:48
      */
    @HystrixCommand
    @GetMapping("/getDefaultFallbackByServerException")
    public String getDefaultFallbackByServerException() {
        //  服务内部异常，会触发服务降级
        throw new RuntimeException("发送异常了");
    }

    /**
      * @Description: 请求响应超时，触发服务降级，Hystrix默认服务请求超时时间为一秒（1s）
      * 当前请求未超时，故未触发降级
      * @return:
      * @author:
      * @date:   2018/11/26 22:54
      */
    @HystrixCommand(commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
	})
    @GetMapping("/getMessageByTimeIn")
    public String getMessageByTimeIn() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "当前线程休眠两秒后返回的信息";
    }

    /**
     * @Description: 请求响应超时，触发服务降级，Hystrix默认服务请求超时时间为一秒（1s）
     * 当前请求已超时，故触发降级
     * @return:
     * @author:
     * @date:   2018/11/26 22:54
     */
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    @GetMapping("/getMessageByTimeOut")
    public String getMessageByTimeOut() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "当前线程休眠两秒后返回的信息";
    }


    /**
      * @Description: 服务熔断规则配置示例
      * @param:
      * @return:
      * @author:
      * @date:   2018/11/27 20:01
      */
    @HystrixCommand(commandProperties = {
            // 设置熔断（即开启熔断机制）
			@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
            // 请求数达到后才计算
			@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
            // 休眠时间窗
			@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
            // 错误率
			@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),
	})
    @GetMapping("/getMessageByHystrixProperty")
    public String getMessageByHystrixProperty() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "当前线程休眠两秒后返回的信息";
    }

    /**
      * @Description: 使用配置文件全局配置信息
      * @param:
      * @return:
      * @author:
      * @date:   2018/11/27 20:04
      */
    @HystrixCommand
    @GetMapping("/getProductInfoList")
    public String getProductInfoList(@RequestParam("number") Integer number) {
        if (number % 2 == 0) {
            return "success";
        }

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "当前线程休眠两秒后返回的信息";
    }

    /**
     * @Description: 使用配置文件指定方法熔断配置信息
     * @param:
     * @return:
     * @author:
     * @date:   2018/11/27 20:04
     */
    @HystrixCommand
    @GetMapping("/getProductInfo")
    public String getProductInfo(@RequestParam("number") Integer number) {
        if (number % 2 == 0) {
            return "success";
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "当前线程休眠两秒后返回的信息";
    }

    private String fallback() {
        return "太拥挤了, 请稍后再试~~";
    }

    private String defaultFallback() {
        return "默认提示：太拥挤了, 请稍后再试~~";
    }
}